package wblog.web;

import cn.webwheel.Action;
import cn.webwheel.results.ErrorResult;
import cn.webwheel.results.RedirectResult;
import cn.webwheel.results.TemplateResult;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import wblog.domain.Article;
import wblog.domain.Comment;
import wblog.domain.User;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

public class article extends home {

    public Article article;

    List<Comment> comments;

    @Action("edit_article.html")
    public Object editPage() throws SQLException {
        if (getLoginUser() == null) {
            return new RedirectResult("/");
        }
        if (article != null) {
            article = qr.query("select * from Article where id=?", new BeanHandler<Article>(Article.class), this.article.id);
            if (article == null) {
                return new ErrorResult(404);
            }
        } else {
            article = new Article();
        }
        return new TemplateResult(this);
    }

    @Action
    public Object update() throws SQLException {

        if (getLoginUser() == null) {
            return err("请登录");
        }

        if (article.title.length() < 1 || article.title.length() > 256) return err("标题长度错误");
        if (article.content.length() < 1 || article.content.length() > 4096) return err("正文长度错误");
        if (article.tags.length() > 256) return err("标签长度错误");

        Set<String> tags = new HashSet<String>();
        for (String s : article.tags.split("\\s+")) {
            if (s.isEmpty()) continue;
            if (s.length() > 16) return err("标签长度错误");
            tags.add(s);
        }

        Connection con = qr.getDataSource().getConnection();
        try {
            con.setAutoCommit(false);
            if (article.id == 0) {
                qr.update(con, "insert into Article(title, content, postDate, authorId, tags) values(?, ?, current_timestamp(), ?, ?)",
                        article.title, article.content, getLoginUser().id, article.tags);
                article.id = qr.query(con, "call identity()", new ScalarHandler<Number>()).intValue();
            } else {
                String uid = qr.query(con, "select authorId from Article where id=?", new ScalarHandler<String>(), article.id);
                if (uid == null) {
                    return err("文章不存在");
                }
                if (!uid.equals(getLoginUser().id)) {
                    return err("权限错误");
                }
                qr.update(con, "update Article set title=?, content=?, tags=? where id=?",
                        article.title, article.content, article.tags, article.id);
                qr.update(con, "delete from ArticleTag where articleId=?", article.id);
            }
            for (String tag : tags) {
                qr.update(con, "insert into ArticleTag(tag, articleId) values(?, ?)", tag, article.id);
            }
            StringBuilder sb = new StringBuilder();
            sb.append(qr.query("select count(*) from Article where authorId=?", new ScalarHandler<Number>(), getLoginUser().id));
            final Map<String, Integer> tagMap = new HashMap<String, Integer>();
            qr.query(con, "select at.tag, count(at.tag) from Article a join ArticleTag at on a.id=at.articleId where a.authorId=? group by at.tag", new ResultSetHandler() {
                @Override
                public Object handle(ResultSet rs) throws SQLException {
                    while (rs.next()) {
                        tagMap.put(rs.getString(1), rs.getInt(2));
                    }
                    return null;
                }
            }, getLoginUser().id);
            for (Map.Entry<String, Integer> entry : tagMap.entrySet()) {
                String s = ' ' + entry.getKey() + ' ' + entry.getValue();
                if (s.length() + sb.length() > 1024) {
                    break;
                }
                sb.append(s);
            }
            qr.update(con, "update User set tags=? where id=?", sb.toString(), getLoginUser().id);
            con.commit();
        } catch (SQLException e) {
            con.rollback();
            throw e;
        } finally {
            con.setAutoCommit(true);
            con.close();
        }

        return ok().set("id", article.id);
    }

    @Action(value = "?article.id=$1&pg=$3", rest = "/article/(\\d+)(/(\\d+))?")
    public Object html() throws SQLException {
        article = qr.query("select * from Article where id=?", new BeanHandler<Article>(Article.class), article.id);
        if (article == null) {
            return new ErrorResult(404);
        }
        qr.update("update Article set view=view+1 where id=?", article.id);
        user = qr.query("select * from User where id=?", new BeanHandler<User>(User.class), article.authorId);
        if (user == null) {
            return new ErrorResult(404);
        }
        String[] tags = article.getTagList();
        if (tags.length > 0) {
            tag = tags[0];
        }
        itemCount = qr.query("select count(*) from Comment where articleId=?", new ScalarHandler<Number>(), article.id).intValue();
        comments = qr.query("select * from Comment join User on Comment.authorId=User.id where articleId=? order by postDate desc limit ? offset ?",
                new ResultSetHandler<List<Comment>>() {
                    @Override
                    public List<Comment> handle(ResultSet rs) throws SQLException {
                        List<Comment> list = new ArrayList<Comment>();
                        while (rs.next()) {
                            Comment comment = new Comment();
                            comment.id = rs.getLong("Comment.id");
                            comment.content = rs.getString("content");
                            comment.postDate = rs.getTimestamp("postDate");
                            comment.author = new User();
                            comment.author.id = rs.getString("User.id");
                            comment.author.name = rs.getString("User.name");
                            comment.author.tags = rs.getString("User.tags");
                            list.add(comment);
                        }
                        return list;
                    }
                }, article.id, pageSize, (pg - 1) * pageSize);
        return new TemplateResult(this);
    }

    @Action
    public Object addComment(String comment) throws SQLException {
        String uid = loginUserService.getLoginUserId();
        if (uid == null) {
            return err("请登录");
        }
        comment = comment.trim();
        if (comment.length() < 1 || comment.length() > 512) return err("评论长度错误");
        Connection con = qr.getDataSource().getConnection();
        try {
            con.setAutoCommit(false);
            qr.update(con, "insert into Comment(articleId, content, authorId, postDate) values(?, ?, ?, current_timestamp())", article.id, comment, uid);
            qr.update(con, "update Article set commentCount = commentCount + 1 where id=?", article.id);
            con.commit();
        } catch (SQLException e) {
            con.rollback();
            throw e;
        } finally {
            con.setAutoCommit(true);
            con.close();
        }
        return ok();
    }

    @Action
    public Object delComment(int id) throws SQLException {
        String uid = loginUserService.getLoginUserId();
        if (uid == null) {
            return err("请登录");
        }
        Connection con = qr.getDataSource().getConnection();
        try {
            con.setAutoCommit(false);
            Number aid = qr.query("select articleId from Comment where id=? and authorId=?", new ScalarHandler<Number>(), id, uid);
            if (aid == null) {
                return err("评论不存在");
            }
            qr.update("delete from Comment where id=? and authorId=?", id, uid);
            qr.update(con, "update Article set commentCount = commentCount - 1 where id=?", aid);
            con.commit();
        } catch (SQLException e) {
            con.rollback();
            throw e;
        } finally {
            con.setAutoCommit(true);
            con.close();
        }

        return ok();
    }

    public List<Comment> getComments() {
        return comments;
    }

    public Collection<String> rand(Collection<String> tags, int count) {
        if (count >= tags.size()) return tags;
        List<String> list = new ArrayList<String>(tags);
        Collections.shuffle(list);
        return list.subList(0, count);
    }
}
